package com.wakyde.collection;

import java.util.*;

/**
 * HashMap和Hashtable的区别？
 * HashMap和HashSet的区别？
 * HashMap和TreeMap区别？
 */
public class MapDemo01 {
    public static void main(String[] args) {
        // HashMap和HashTable的区别？
        /*
            1.HashMap可以添加null值， Hashtable不可以
            2.HashMap线程不安全，而Hashtable线程安全
            3.初始扩充容量大小和每次扩充容量大小不同
            4.底层数据结构处理机制有些不同
            5.HashMap性能要比Hashtable稍好一些，因为Hashtable的方法都经过synchronized修饰
        **/
        // tableSizeFor函数每次扩容: 2的幂次方
        // 初始容量是16，初始容量不管给定多少，容量都是2的幂次方
        // 当链表长度大于阀值（8），链表会自动转换成红黑树; 将链表转换为红黑树之前，hashMap会先进行判断数组的容量是否大于64，如果小于，则先进行扩容;
        // 底层结构 数组 + 双向链表 或者 数组 + 红黑树
        Map<String, String> map = new HashMap<>();
        map.put("1", null);
        // rehash()函数每次扩容: int newCapacity = (oldCapacity << 1) + 1;
        // 由此可看出每次扩容是2n+1
        // 初始容量是11，如果初始容量给定初始值，它就是使用这个初始值
        // 没有转换机制
        // 底层结构 数组 + 双向链表
        Map<String, String> map1 = new Hashtable<>();
//        map1.put("1", null);

        // HashMap和HashSet的区别？
        /*
            1.HashSet没有键值对区分，只保留了key, value是一个空对象， 而HashMap的key和value是有意的
            2.HashSet实现了Set接口，HashMap实现了Map接口
            3.计算hashcode值的方式不同 HashMap是由Key生成的值，而HashSet是由对象中的元素生成的，且需要通过equals判断元素是否相同
            4.添加元素的方式不一样 HashMap调用Map来添加元素， HashSet调用add添加
         */
        Set<String> set = new HashSet<>();
        set.add(null);

        // HashMap和TreeMap区别？
        /*
            1.TreeMap 实现了NavigableMap，拥有了搜索和排序的能力， 而HashMap没有
         */
        Map<Person, String> map2 = new TreeMap<>((Person person1, Person person2) -> {
            int num = person1.getAge() - person2.getAge();
            return Integer.compare(num, 0);
        });
        map2.put(new Person(4), "p1");
        map2.put(new Person(1), "p2");
        map2.put(new Person(3), "p3");
        map2.put(new Person(2), "p4");
        map2.entrySet().forEach(item -> {
            System.out.println(item.getValue());
        });
    }

    static class Person{
        private int age;

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public Person(int age) {
            this.age = age;
        }
    }
}
